//? 类型推断
let str = "1234";
let num = 234;
let bool = false;

let any; // 如果创建时候 没有赋值 则不会触发类型检查

// 函数的返回值也会被类型推断
function reNum(num1: number, num2: number) {
  return num1 + num2;
}

//? 类型断言
interface Person {
  age: number;
  name: string;
}

// const person = <Person>{};
const person = {} as Person;

person.name = "xuzy";
person.age = 25;

//? 双重断言
const person2 = "andy" as any as Person;

//? 非空断言
let flag: null | undefined | string;

//非空断言用!表示，它用来断定某变量一定不是 null 和 undefined
flag!.toString();
flag?.toLocaleLowerCase();

//? 确定赋值断言
// 告知编译器，这玩意一定会被赋值 所以不会报错
let xx!: number;

getTwo(xx);

console.log(xx);

function getTwo(num: number) {
  num = 2;
  return num;
}

//? 类型守卫
function double(input: string | number | boolean) {
  if (typeof input === "string") {
    return input + input;
  }
  if (typeof input === "number") {
    return input * 2;
  }
  if (typeof input === "boolean") {
    return !input;
  }
}

class Person3 {
  name = "xuzy";
  age = 25;
}

class Animal3 {
  name = "doge";
  color = "yellow";
}

function getSomeThing(arg: Person3 | Animal3) {
  // 不使用类型守卫，一定会报错
  //   !console.log(arg.age);
  //   !console.log(arg.color);
  if (arg instanceof Person3) {
    console.log(arg.age);
  }

  if (arg instanceof Animal3) {
    console.log(arg.color);
  }
}
export {};
class Person4 {
  name = "xuzy";
  age = 25;
}

class Animal4 {
  name = "doge";
  color = "black";
}

function doSomeThing(arg: Person4 | Animal4) {
  if ("age" in arg) {
    //!console.log(arg.color); 报错，因为推断出的类型里 不包含 color
    console.log(arg.age);
  }

  if ("color" in arg) {
    //! console.log(arg.age); 报错，因为推断出的类型里 不包含 age
    console.log(arg.color);
  }
}

//? 类型别名
type myType = number | string;

const nums: myType = 2;

type container<T> = { value: T };

type Tree<T> = {
  value: T;
  left: Tree<T>;
  right: Tree<T>;
};

const mm: container<number> = {
  value: 2,
};
